﻿using Common.Helpers;
using System.Text.RegularExpressions;

namespace Common.Core.Util
{
    /// <summary>
    /// IP工具类
    /// </summary>
    public static class IpHelper
    {
        /// <summary>
        /// 获取当前IP
        /// </summary>
        /// <returns></returns>
        public static string GetIPAddress(bool includeProxy = false)
        {
            string ip = "";

            if (HttpContextHelper.HttpContext == null) return ip;

            if (HttpContextHelper.HttpContext.Request != null)
            {
                ip = HttpContextHelper.HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
                if (!includeProxy && !string.IsNullOrEmpty(ip) && ip.Contains(","))
                {
                    ip = ip.Split(",")[0];
                }
            }
            if (string.IsNullOrEmpty(ip))
            {
                ip = HttpContextHelper.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
            }

            return ip;
        }

        /// <summary>
        /// 判断IP地址是否本机IP
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IpIsLoopback(string ip)
        {
            return (ip == "127.0.0.1" || ip == "::1" || ip == "localhost");
        }

        /// <summary>
        /// 重载IpToString(ip,false)
        /// </summary>
        /// <param name="ip">IP地址</param>
        /// <returns></returns>
        public static string IpToString(long ip)
        {
            return IpToString(ip, false);
        }

        /// <summary>
        /// 将长整型的IP地址格式化为字符串形式
        /// </summary>
        /// <param name="ip">IP地址</param>
        /// <param name="compact">是否采用紧缩格式化模式（非紧缩时每段自动将0补足）</param>
        /// <returns></returns>
        public static string IpToString(long ip, bool compact)
        {
            int ip4 = (int)(ip % 256);
            ip = ip / 256;
            int ip3 = (int)(ip % 256);
            ip = ip / 256;
            int ip2 = (int)(ip % 256);
            ip = ip / 256;
            int ip1 = (int)(ip % 256);

            string sip1 = ip1.ToString();
            string sip2 = ip2.ToString();
            string sip3 = ip3.ToString();
            string sip4 = ip4.ToString();

            if (!compact)
            {
                if (ip1 < 10) sip1 = "00" + sip1;
                else if (ip1 < 100) sip1 = "0" + sip1;

                if (ip2 < 10) sip2 = "00" + sip2;
                else if (ip2 < 100) sip2 = "0" + sip2;

                if (ip3 < 10) sip3 = "00" + sip3;
                else if (ip3 < 100) sip3 = "0" + sip3;

                if (ip4 < 10) sip4 = "00" + sip4;
                else if (ip4 < 100) sip4 = "0" + sip4;
            }

            return sip1 + "." + sip2 + "." + sip3 + "." + sip4;
        }

        /// <summary>
        /// 将字符串形式的IP地址转换为长整型
        /// </summary>
        /// <param name="sip">IP地址</param>
        /// <returns></returns>
        public static long IpToAddress(string sip)
        {
            string[] ip = sip.Split('.');
            if (ip.Length != 4) return -1;

            int ip1, ip2, ip3, ip4;
            if (!Function.IsInt32(ip[0], out ip1)) return -1;
            if (!Function.IsInt32(ip[1], out ip2)) return -1;
            if (!Function.IsInt32(ip[2], out ip3)) return -1;
            if (!Function.IsInt32(ip[3], out ip4)) return -1;

            long addr = ip1;
            addr = addr * 256 + ip2;
            addr = addr * 256 + ip3;
            addr = addr * 256 + ip4;
            return addr;
        }

        /// <summary>
        /// 检查IP地址格式
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IsIP(string ip)
        {
            return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)(:\d)?$");
        }

        /// <summary>
        /// 判断IP地址是否为内网IP地址
        /// </summary>
        /// <param name="ipAddress">IP地址字符串</param>
        /// <returns></returns>
        public static bool IsInnerIP(String ipAddress)
        {
            bool isInnerIp = false;
            long ipNum = IpToAddress(ipAddress);
            /**
               私有IP：A类  10.0.0.0-10.255.255.255
                       B类  172.16.0.0-172.31.255.255
                       C类  192.168.0.0-192.168.255.255
                       当然，还有127这个网段是环回地址   
              **/
            long aBegin = IpToAddress("10.0.0.0");
            long aEnd = IpToAddress("10.255.255.255");
            long bBegin = IpToAddress("172.16.0.0");
            long bEnd = IpToAddress("172.31.255.255");
            long cBegin = IpToAddress("192.168.0.0");
            long cEnd = IpToAddress("192.168.255.255");
            isInnerIp = IsInner(ipNum, aBegin, aEnd) || IsInner(ipNum, bBegin, bEnd) || IsInner(ipNum, cBegin, cEnd) || ipAddress.Equals("127.0.0.1");
            return isInnerIp;
        }

        /// <summary>
        /// 判断用户IP地址转换为Long型后是否在内网IP地址所在范围
        /// </summary>
        /// <param name="userIp"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private static bool IsInner(long userIp, long begin, long end)
        {
            return (userIp >= begin) && (userIp <= end);
        }
    }
}
